package com.gw.vip.center.zib;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.gw.vip.center.constant.VipCenterConstants;
import com.gw.vip.center.dto.*;
import com.gw.vip.center.jwt.JwtUtil;
import com.gw.vip.center.jwt.TokenInfo;
import com.gw.vip.center.po.UserInfo;
import com.gw.vip.center.po.UserLogin;
import com.gw.vip.center.service.PassWordService;
import com.gw.vip.center.service.dao_service.SysArgService;
import com.gw.vip.center.service.dao_service.UserInfoService;
import com.gw.vip.center.service.UserLoginService;
import com.gw.vip.center.util.RedisUtil;
import com.gw.vip.center.vo.*;
import com.gw.vip.common.constants.VipConstants;
import com.gw.vip.common.enums.TfEnums;
import com.gw.vip.common.exception.ExceptionEnums;
import com.gw.vip.common.exception.ServiceException;
import com.gw.vip.common.util.Snowflake;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Random;

/**
 * @author GW
 * @description
 * @since 2022-03-30
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LoginBiz {
    private final UserLoginService userLoginService;
    private final UserInfoService userInfoService;
    private final WxMaService wxMaService;
    private final Snowflake snowflake;
    private final Random random;
    private final RedisUtil redisUtil;
    private final SysArgService sysArgService;
    private final PassWordService passWordService;

    public UnionLoginVo unionLogin(UnionInfoDto unionInfoDto) {
        UserLogin userLogin = userLoginService.getByBase(unionInfoDto.getChannelId(), unionInfoDto.getUnionId());
        if (userLogin == null){
            log.info("渠道【{}】,联合用户【{}】,第一次登陆。", unionInfoDto.getChannelId(), unionInfoDto.getUnionId());
            throw new ServiceException(ExceptionEnums.NEED_AUTH);
        }

        //没有对应的userId
        if (userLogin.getUserId()==null){
            log.info("渠道【{}】,联合用户【{}】,第一次登陆。", unionInfoDto.getChannelId(), unionInfoDto.getUnionId());
            throw new ServiceException(ExceptionEnums.NEED_AUTH);
        }

        UserInfo userInfo = userInfoService.getById(userLogin.getUserId());
        if (userInfo == null){
            log.error("用户【{}】不存在！", userLogin.getUserId());
            throw new ServiceException(ExceptionEnums.SYSTEM_ERROR);
        }

        //更新登陆信息
        userLogin.setUpdTime(LocalDateTime.now());
        userLoginService.updateById(userLogin);

        //token信息
        TokenInfo tokenInfo = new TokenInfo();
        tokenInfo.setUserId(userInfo.getId());
        String token = JwtUtil.token(tokenInfo);

        UnionLoginVo unionLoginVo = new UnionLoginVo();
        unionLoginVo.setUserInfo(userInfo);
        unionLoginVo.setToken(token);

        return unionLoginVo;
    }

    /**
     * 小程序登录
     * @param miniProgramLoginDto 入参
     * @return 用户信息
     */
    public MiniProgramLoginVo miniProgramLogin(MiniProgramLoginDto miniProgramLoginDto) {
        String code = miniProgramLoginDto.getCode();
        WxMaJscode2SessionResult session;
        try {
            session = wxMaService.getUserService().getSessionInfo(code);
            log.info(session.getSessionKey());
            log.info(session.getOpenid());
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(ExceptionEnums.OTHER_SYSTEM_ERROR, "微信登陆失败");
        }

        MiniProgramLoginVo vo = new MiniProgramLoginVo();
        vo.setUnionId(session.getOpenid());

        try{
            UnionInfoDto unionInfoDto = new UnionInfoDto();
            unionInfoDto.setChannelId(miniProgramLoginDto.getChannelId());
            unionInfoDto.setUnionId(session.getOpenid());
            UnionLoginVo unionLoginVo = this.unionLogin(unionInfoDto);
            vo.setUserInfo(unionLoginVo.getUserInfo());
            vo.setToken(unionLoginVo.getToken());
        }catch (ServiceException se){
            if (se.getCode().equals(ExceptionEnums.NEED_AUTH.getKey())){
                vo.setNeedAuth(TfEnums.TRUE.getKey());
            }else{
                throw se;
            }
        }

        return vo;
    }

    /**
     * 获取用户会话密钥。
     * @param dto
     * @return
     */
    public SessionKeyVo sessionKey(SessionKeyDto dto) {
        int sessionKeyIntFront = random.nextInt(100000000);
        int sessionKeyIntTail = random.nextInt(100000000);
        String sessionKey = String.format("%08d", sessionKeyIntFront)+String.format("%08d", sessionKeyIntTail);
        log.info("渠道【{}】,unionId【{}】,会话密钥【{}】", dto.getChannelId(), dto.getUnionId(), sessionKey);

        redisUtil.set(VipCenterConstants.SESSION_KEY+":"+dto.getChannelId()+":"+dto.getUnionId(), sessionKey);

        SessionKeyVo vo = new SessionKeyVo();
        vo.setSessionKey(sessionKey);

        return vo;
    }

    /**
     * 邮箱密码登录
     * @param dto
     * @return
     */
    public MailPassWordLoginVo mailPassWordLogin(MailPassWordLoginDto dto) {
        UserInfo userInfo = userInfoService.getByMail(dto.getMailAddress());
        if (userInfo==null){
            log.error("用户不存在！邮箱【{}】", dto.getMailAddress());
            throw new ServiceException(ExceptionEnums.USER_NOT_EXIST);
        }

        //解密
        String passWord = passWordService.decrypt(dto.getEncPassWord(), dto.getChannelId(), dto.getUnionId());
        //对比密码
        if (!userInfo.getPassword().equals(passWord)){
            log.error("密码不正确！上送密码【{}】，数据库密码【{}】", passWord, userInfo.getPassword());
            throw new ServiceException(ExceptionEnums.ERROR_PASSWORD);
        }

        //登录信息处理
        UserLogin userLogin = userLoginService.getByBase(dto.getChannelId(), dto.getUnionId());
        if (userLogin!=null){
            //更新
            userLogin.setUpdTime(LocalDateTime.now());
            userLoginService.updateById(userLogin);
        }else {
            //插入
            userLogin = new UserLogin();
            userLogin.setId(snowflake.nextId());
            userLogin.setChannelId(dto.getChannelId());
            userLogin.setUnionId(dto.getUnionId());
            userLogin.setUserId(userInfo.getId());
            userLogin.setCrtTime(LocalDateTime.now());
            userLogin.setCrtName(VipConstants.SYS);
            userLogin.setUpdTime(userLogin.getCrtTime());
            userLogin.setUpdName(VipConstants.SYS);
            userLoginService.save(userLogin);
        }


        //token信息
        TokenInfo tokenInfo = new TokenInfo();
        tokenInfo.setUserId(userInfo.getId());
        String token = JwtUtil.token(tokenInfo);

        MailPassWordLoginVo vo = new MailPassWordLoginVo();
        vo.setUserInfo(userInfo);
        vo.setToken(token);
        return vo;
    }
}
